#include "stdAfx.h"
#include "DPComparator.h"


struct sortclass {
  bool operator() (int i,int j) { return (i<j);}
} sortobject;

void DPComparator::setErrorMatrix(Matrix* errorMatrix,int sizeOne,int sizeTwo)
{
   this->errorMatrix=errorMatrix;  
    minSize = sizeOne;
    maxSize = sizeTwo;    
}

//void DPComparator::setMinMaxSize(int sizeOne,int sizeTwo)
//{
//    if(sizeOne>sizeTwo)
//    {
//        minSize = sizeTwo;
//        maxSize = sizeOne;
//    }
//    else
//    {
//        minSize = sizeOne;
//        maxSize = sizeTwo;
//    }
//}
 
float DPComparator::calculateDPError()
{
    float minAverage;
    int** newContourMat = new int*[minSize];
	int** pMat = new int*[minSize];
	int** qMat = new int*[minSize];

	float** errorOutPut = new float*[minSize];
	
	int* tmpRow;

	float* tmpDoubleRow;

	for(int i=0;i<minSize;i++){
		tmpRow = new int[minSize];
		tmpRow[i]=-1;
		newContourMat[i] = tmpRow;
		
		tmpRow = new int[minSize];
		tmpRow[i]=-1;
		pMat[i] = tmpRow;		
		tmpRow = new int[minSize];
		tmpRow[i]=-1;
		qMat[i] = tmpRow;

		tmpDoubleRow= new float[minSize];
		errorOutPut[i] = tmpDoubleRow;
	}
	
	Matrix* matrixNewContour  = new Matrix(newContourMat,minSize,minSize);
	Matrix* pMatrix  = new Matrix(pMat,minSize,minSize);
	Matrix* qMatrix  = new Matrix(qMat,minSize,minSize);
	
	Matrix* errorOutPutMatrix  = new Matrix(errorOutPut,minSize,minSize);
	
	int def=0;
	int a,b;
	list<int>* returnColumnRemoveList;
	list<float>* getRowMinList;
	for(int i=0;i<minSize;i++)
	{
		for(int j=0;j<(minSize-i);j++)
		{
			a=j;
			b=j+def;
			returnColumnRemoveList = new list<int>();
			getRowMinList = new list<float>();
			
			
			if(a==b)
			{				
				int newContourIndex;
				getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a,b);
				//list<float>* getRowMinList = getRowMin(errorMatrix,returnColumnRemoveList,a);
				getRowMin(errorMatrix,returnColumnRemoveList,getRowMinList,a);
				//errorOutPutMatrix->setVal(a,b,getRowMin(matAllErrors,returnColumnRemoveList,a,newContourIndex));
				errorOutPutMatrix->setVal(a,b,getRowMinList->front());
				getRowMinList->pop_front();
				newContourIndex = getRowMinList->front();
				matrixNewContour->setValIntMat(a,b,newContourIndex);
				getRowMinList->clear();
				//delete getRowMinList; 
				returnColumnRemoveList->clear();
			}
			else
			{
				int aMinusOneIndex;
				//getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a-1,b);
				getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a,b-1);  // changed on 22 11 2012
				//getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a,b);
				//getRowMinList = getRowMin(matAllErrors,returnColumnRemoveList,a); // check hear
				//list<float>* getRowMinListAMinusOne = getRowMin(errorMatrix,returnColumnRemoveList,b); // check hear
				getRowMin(errorMatrix,returnColumnRemoveList,getRowMinList,b); // check hear
				//double aMinusOne = getRowMin(matAllErrors,returnColumnRemoveList,a,aMinusOneIndex)+ errorOutPutMatrix->getVal(a-1,b);
				//double aMinusOne = getRowMinList->front()+ errorOutPutMatrix->getVal(a-1,b);
				float aMinusOne = getRowMinList->front()+ errorOutPutMatrix->getVal(a,b-1);
				getRowMinList->pop_front();
				aMinusOneIndex=getRowMinList->front();
				getRowMinList->clear();
				 
				returnColumnRemoveList->clear();
				//delete getRowMinListAMinusOne;

				int bPlusOneIndex;
				//getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a,b+1);
				getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a+1,b); // changed on 22 11 2012
				//getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,a,b);
				//getRowMinList = getRowMin(matAllErrors,returnColumnRemoveList,b); // check hear
				//list<float>* getRowMinListBPlusOne = getRowMin(errorMatrix,returnColumnRemoveList,a); // check hear
				getRowMin(errorMatrix,returnColumnRemoveList,getRowMinList,a); // check hear
				//double bPlusOne = getRowMin(matAllErrors,returnColumnRemoveList,b,bPlusOneIndex)+ errorOutPutMatrix->getVal(a,b+1);
				//double bPlusOne = getRowMinList->front()+ errorOutPutMatrix->getVal(a,b+1);
				float bPlusOne = getRowMinList->front()+ errorOutPutMatrix->getVal(a+1,b);
				getRowMinList->pop_front();
				bPlusOneIndex=getRowMinList->front();
				getRowMinList->clear();
				 
				returnColumnRemoveList->clear();
			   // delete getRowMinListBPlusOne;
			    
				errorOutPutMatrix->setVal(a,b,minVal(aMinusOne,bPlusOne));


				if(minVal(aMinusOne,bPlusOne)==aMinusOne){
					matrixNewContour->setValIntMat(a,b,aMinusOneIndex);
					//pMatrix->setValIntMat(a,b,(a-1));
					pMatrix->setValIntMat(a,b,a);
					//qMatrix->setValIntMat(a,b,b);				
					qMatrix->setValIntMat(a,b,b-1);				
				}else{
					matrixNewContour->setValIntMat(a,b,bPlusOneIndex);
					/*pMatrix->setValIntMat(a,b,a);
					qMatrix->setValIntMat(a,b,(b+1));*/
					pMatrix->setValIntMat(a,b,a+1);
					qMatrix->setValIntMat(a,b,b);
				
				}

			}
			
			delete getRowMinList;
			delete returnColumnRemoveList;
			//def++;
	    }
	    def++;
    }
    minAverage = errorOutPutMatrix->getVal(0,(minSize-1))/minSize;
    
    delete qMatrix;
	delete pMatrix;
	delete matrixNewContour;
	delete errorOutPutMatrix;
	//delete matAllErrors;
	
	printf("Dayanamic Match Error : %f",minAverage);
    
    
	
    return minAverage;
}

void DPComparator::getColumnRemoveList(Matrix* matrixNewContour,Matrix* pMatrix,Matrix* qMatrix,list<int>* returnColumnRemoveList,int p,int q){

	//list<int>* returnColumnRemoveList = new list<int>();

	if(p==-1&&q==-1){
	  //  return;
		returnColumnRemoveList->push_back(-1);
		
	}else
	{
		returnColumnRemoveList->push_back(matrixNewContour->getValIntMat(p,q));
		int PTemp = p;
		int QTemp = q;

		p=pMatrix->getValIntMat(PTemp,QTemp);
		q=qMatrix->getValIntMat(PTemp,QTemp);
		
		//if(p==-1&&q==-1)
		{
		    //returnColumnRemoveList->push_back(-1);
		}
		//else
		{
		    getColumnRemoveList(matrixNewContour,pMatrix,qMatrix,returnColumnRemoveList,p,q);
		}
	
	}
}

//list<float>* DPComparator::getRowMin(Matrix* errormatrix,list<int>* columnRemoveList, int row){
void DPComparator::getRowMin(Matrix* matrix,list<int>* columnRemoveList,list<float>* returnRowMinList, int row){

    returnRowMinList->clear();
	//list<float>* returnList = new list<float>();
	float min = 9999999999; 
	columnRemoveList->sort(sortobject);	//columnRemoveList->begin(),columnRemoveList->end(),
	 int tempnewContourIndex=-1;
	//while(true)
	{  
	    
	    int peak = columnRemoveList->front();
	    if(peak==-1)
	    {
	      columnRemoveList->pop_front();
	      if(!columnRemoveList->empty())
	      {
	        peak = columnRemoveList->front();	      
	      }
	    }
	    
	    if(peak!=-1)
	    {
	    
	    
	    }
	    //int end =  columnRemoveList->end();
	   // int tempnewContourIndex=-1;
    	
	    for(int j=0;j<matrix->getJMax();j++)
	    {
	        if(peak==-1||0<j<peak)
	        {
	            if(matrix->getVal(row,j)<min)
	            {
	                min = matrix->getVal(row,j);
				    tempnewContourIndex=j;
	            } 
	        }
	        else  if(peak==j)
	        {
	            columnRemoveList->pop_front();
	           if(!columnRemoveList->empty())
	           {
	                peak = columnRemoveList->front();	      
	           }
	           else
	           {
	              peak=-1;
	           }
	        
	        }
	    
		    /*if(peak != j){
			    if(matrix->getVal(row,j)<min){
				    min = matrix->getVal(row,j);
				    tempnewContourIndex=j;
			    }
		    }else if(peak==j){
			    columnRemoveList->pop_front();	
			    if(!columnRemoveList->empty()){
				    peak = columnRemoveList->front();
			    }
		    }*/	
	    }
	}
	
	//for(int j=0;j<matrix->jMax;j++){
	/*for(int j=0;j<matrix->getJMax();j++){
		if(peak != j){
			if(matrix->getVal(row,j)<min){
				min = matrix->getVal(row,j);
				tempnewContourIndex=j;
			}
		}else if(peak==j){
			columnRemoveList->pop_front();	
			if(!columnRemoveList->empty()){
				peak = columnRemoveList->front();
			}
		}	
	}*/
	//newContourIndex = &tempnewContourIndex;
	returnRowMinList->push_back(min);
	returnRowMinList->push_back(tempnewContourIndex);
	//return returnRowMinList;
}
float DPComparator::minVal(float value1, float value2){
	if(value1>value2){
		return value2;
	}else{
		return value1;           // if value1 = value2 this returns value1
	}
}

DPComparator::~DPComparator(void)
{
    delete errorMatrix;
}